<script setup lang="ts">
import { ref, watch, onMounted } from 'vue'
import { getSlideImage, captchaVerify } from '@/api/common/account'
import { VerifyType } from '@/api/common/account/types'

const props = defineProps({
  buttonText: {
    type: String,
    default: '>>'
  },
  showText: {
    type: String,
    default: 'Please puzzle'
  },
  successText: {
    type: String,
    default: 'Successfully Verified'
  },
  failureText: {
    type: String,
    default: 'Failure Verified'
  },
  forbiddenText: {
    type: String,
    default: 'Too many retries are disabled'
  },
  initTime: {
    type: String,
    default: ''
  }
})

const emits = defineEmits(['captcha_status'])

const slider_button = ref()
const slider_box = ref()
const code_imgBG = ref()
const code_imgBlock = ref()
const slider_bg = ref()
const code_box = ref()
const slider_text = ref()

const codeValue = ref<string>('')
const codeState = ref<string>('')
// const duration = ref<number>(200)
const swipestart = ref<boolean>(false)
const min = ref<number>(0)
const max = ref<number>(100)
const index = ref<number>(0)
const buttonIndex = ref<number>(0)
const sliderButtonText = ref(props.buttonText)
const sliderText = ref(props.showText)

watch(
  () => props.initTime,
  () => {
    fn_reset()
    captcha_get()
  }
)

onMounted(() => {
  fn_init()
  captcha_get()
})

const fn_init = () => {
  fn_updateView()
  fn_sliderBtnEvent(true)
}
const fn_handerIn = () => {
  swipestart.value = true
  min.value = 0
  max.value = slider_box.value.offsetWidth

  document.addEventListener('mousemove', fn_handerMove)
  document.addEventListener('mouseup', fn_handerOut)
  document.addEventListener('touchmove', fn_handerMoveMobile)
  document.addEventListener('touchend', fn_handerOut)
  fn_sliderbox_mouseover()
}
const fn_handerOut = () => {
  swipestart.value = false

  document.removeEventListener('mousemove', fn_handerMove)
  document.removeEventListener('mouseup', fn_handerOut)
  document.removeEventListener('touchmove', fn_handerMoveMobile)
  document.removeEventListener('touchend', fn_handerOut)

  captcha_verify()
  fn_sliderbox_mouseout()
}
const fn_handerMove = (event: any) => {
  if (swipestart.value) {
    event.preventDefault()
    event = event || window.event
    index.value = event.clientX - buttonIndex.value
    code_imgBlock.value.style.left = index.value + 'px'
    fn_move()
  }
}
const fn_handerMoveMobile = (event: any) => {
  if (swipestart.value) {
    event = event || window.event
    index.value = event.touches[0].pageX - buttonIndex.value
    code_imgBlock.value.style.left = index.value + 'px'
    fn_move()
  }
}
const fn_move = () => {
  if (index.value + slider_button.value.offsetWidth >= max.value) {
    index.value = max.value - slider_button.value.offsetWidth - 2
    swipestart.value = false
  }
  if (index.value < 0) {
    index.value = min.value
  }
  fn_updateView()
}
const fn_updateView = () => {
  slider_bg.value.style.width = index.value + 'px'
  slider_button.value.style.left = index.value + 'px'
}
const fn_sliderBtnEvent = (isAdd: boolean) => {
  if (isAdd === true) {
    slider_button.value.addEventListener('mousedown', fn_sliderbutton_mousedown)
    slider_button.value.addEventListener('touchstart', fn_sliderbutton_touchstart)
  } else {
    for (let i = 0; i < 5; i++) {
      slider_button.value.removeEventListener('mousedown', fn_sliderbutton_mousedown)
      slider_button.value.removeEventListener('touchstart', fn_sliderbutton_touchstart)
    }
  }
}
const fn_sliderbutton_mousedown = (event: any) => {
  const e = event || window.event
  buttonIndex.value = e.clientX - slider_button.value.offsetLeft
  fn_handerIn()
}
const fn_sliderbutton_touchstart = (event: any) => {
  const e = event || window.event
  buttonIndex.value = e.touches[0].pageX - slider_button.value.offsetLeft
  fn_handerIn()
}
const fn_sliderbox_mouseover = () => {
  if (!codeState.value) {
    code_box.value.style.display = 'block'
    if (!codeState.value) {
      const offset_x =
        parseInt(slider_box.value.getBoundingClientRect().left) -
        parseInt(document.body.scrollLeft.toString(), 10) // 10：十进制解析
      const offset_y =
        parseInt(slider_box.value.getBoundingClientRect().top) -
        parseInt(document.body.scrollTop.toString(), 10) -
        parseInt(code_box.value.offsetHeight)
      code_box.value.style.left = offset_x + 'px'
      code_box.value.style.top = offset_y + 'px'
    }
  }
}
const fn_sliderbox_mouseout = () => {
  code_box.value.style.display = 'none'
}
const fn_reset = () => {
  code_box.value.style.display = 'none'
  code_box.value.style.left = '0px'
  code_box.value.style.top = '0px'
  code_imgBlock.value.style.left = '0px'
  code_imgBlock.value.style.top = '0px'

  slider_bg.value.style.width = '0px'
  slider_bg.value.style.backgroundColor = '#75CDF9'
  slider_button.value.style.left = '0px'
  slider_button.value.style.display = 'block'

  swipestart.value = false
  index.value = 0
  buttonIndex.value = 0
  codeState.value = ''
  codeValue.value = ''

  sliderText.value = props.showText
  slider_text.value.style.color = '#222222'
  fn_init()
}

const captcha_get = async () => {
  getSlideImage()
    .then((result) => {
      code_imgBG.value.src = result.Image_Base64
      code_imgBlock.value.src = result.Image2_Base64
      code_imgBlock.value.style.left = result.Image2_Offset_X + 'px'
      code_imgBlock.value.style.top = result.Image2_Offset_Y + 'px'
      codeValue.value = result.Id ?? ''
    })
    .catch((error) => {
      emits('captcha_status', { MsgCode: '400', MsgData: '', MsgError: error })
      fn_sliderBtnEvent(false)
    })
}
const captcha_verify = () => {
  const pItem: VerifyType = {
    Id: codeValue.value,
    Type: 'SlideImage',
    DataCode: parseInt(code_imgBlock.value.offsetLeft)
  }

  if (pItem.DataCode >= 0 && pItem.DataCode <= 500) {
    slider_button.value.style.display = 'none'
    captchaVerify(pItem)
      .then((result) => {
        if (result.MsgCode === '200') {
          // 成功
          sliderText.value = props.successText
          slider_text.value.style.color = '#00CC33'

          // 登记状态
          code_box.value.style.display = 'none'
          codeState.value = '1'
          emits('captcha_status', { MsgCode: '200', MsgData: codeValue.value, MsgError: '' })
        } else {
          // 失败
          sliderText.value = props.failureText
          slider_text.value.style.color = '#ff0000'

          // 延迟重试
          setTimeout(function () {
            fn_reset() // 重置参数值
            captcha_get() // 刷新验证码
          }, 1000)
        }

        slider_bg.value.style.backgroundColor = '#e8e8e8'
        index.value = max.value
        fn_updateView()
        fn_sliderBtnEvent(false)
      })
      .catch((error) => {
        emits('captcha_status', { MsgCode: '400', MsgData: '', MsgError: error })
        fn_sliderBtnEvent(false)
      })
  }
}
</script>

<template>
  <div>
    <div
      ref="code_box"
      class="m-auto w-320px h-170px fixed rounded-[2px] bg-[#e8e8e8] overflow-hidden select-none z-100 hidden"
    >
      <img ref="code_imgBG" class="absolute left-0 top-0 w-320px h-170px z-101" />
      <img ref="code_imgBlock" class="absolute left-0 top-0 w-40px h-40px z-102" />
    </div>
    <div
      ref="slider_box"
      class="m-auto h-40px relative rounded-[2px] bg-[#e8e8e8] overflow-hidden text-center select-none z-0"
      @mouseover="fn_sliderbox_mouseover"
      @mouseout="fn_sliderbox_mouseout"
    >
      <div ref="slider_bg" class="absolute left-0 top-0 h-full bg-[#75cdf9] z-1"></div>
      <span
        ref="slider_button"
        class="w-38px absolute left-1px top-1px h-38px flex items-center justify-center dark:(border-1 border-[#ccc] border-solid) bg-white z-3 cursor-move text-[#666] text-14px font-sans"
        >拖动</span
      >
      <span
        ref="slider_text"
        class="absolute left-0 w-full h-full text-16px font-serif text-[#222] leading-40px text-center z-2"
        >验证成功</span
      >
    </div>
  </div>
</template>

<style lang="less" scoped></style>
